package org.liveboardgames.agricola.business;

import java.util.ArrayList;
import java.util.List;

import org.liveboardgames.agricola.access.IGameDao;
import org.liveboardgames.agricola.business.action.overrideaction.ActionOverrider;
import org.liveboardgames.agricola.business.action.processor.ActionProcessor;
import org.liveboardgames.agricola.business.action.processor.ActionProcessorFactory;
import org.liveboardgames.agricola.business.helper.GameHelper;
import org.liveboardgames.agricola.controller.AgricolaUpdateAdapter;
import org.liveboardgames.agricola.domain.Change;
import org.liveboardgames.agricola.domain.Game;
import org.liveboardgames.agricola.domain.action.Action;
import org.liveboardgames.agricola.domain.common.Target;

public class ActionServiceImpl implements IActionService {

  private IGameDao gameDao;

  public void setGameDao(IGameDao gameDao) {
    this.gameDao = gameDao;
  }

  public void executeAction(Long gameId, Long actionId, Long targetId, String targetType) {

    Game game = gameDao.load(gameId);

    Action action = new GameHelper().findAction(game, actionId);
    Target target = findTarget(game, targetType, targetId);
    List<Change> changes = executeAction(game, action, target);

    gameDao.save(game);

    new AgricolaUpdateAdapter().publishGameUpdates(gameId, changes);
  }

  public List<Change> executeAction(Game game, Action action, Target target) {
    // Override the action depending on who performs it (for instance when the
    // player has dedicated bonii on one action)
    Action overriddenAction = new ActionOverrider().overrideAction(action, target);

    String outputType = overriddenAction.getActionOutput();

    int outputQuantity = overriddenAction.getOutputQuantity();

    // Now we have everything we need to execute the
    // minimal part of the action
    // We retrieve the class that will proces this
    List<Change> changes = new ArrayList<Change>();
    ActionProcessor actionProcessor =
        ActionProcessorFactory.getProcessor(game, outputType, outputQuantity, overriddenAction, changes);

    // Part where the action is really executed
    actionProcessor.execute();

    return changes;
  }

  private Target findTarget(Game game, String targetType, Long targetId) {
    Target target = null;

    if (targetType != null) {
      if (targetType.equals("BoardTile")) {
        target = new GameHelper().findBoardTile(game, targetId);
      }
      else if (targetType.equals("Card")) {
        target = new GameHelper().findCard(game, targetId);
      }
      else if (targetType.equals("Player")) {
        target = new GameHelper().findPlayer(game, targetId);
      }
    }

    return target;
  }
}
